package com.kaiyidiannao.https;

import android.content.Context;
import android.util.Log;
import com.kaiyidiannao.data.DataCenter;
import com.kaiyidiannao.main.R;
import com.kaiyidiannao.model.AppSignal;
import com.kaiyidiannao.model.Result;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by david on 14-4-11.
 */
public class CustomHttpClient {
    private static final String CHARSET_UTF8 = HTTP.UTF_8;
    private static final String TAG = "CustomHttpClient";
    private static DefaultHttpClient customerHttpClient;
    private static final int REQUEST_TIMEOUT = 30000;
    private static final int SO_TIMEOUT = 30000;

    public CustomHttpClient() {
        super();
    }

    //---------------------------------------Http请求返回状态进行封装（三次封装）------------------------------------------------------

    /**
     * HttpClient GET 提交数据,返回的json字符串封装到Result.object对象,请求状态封装到Result.status中
     *
     * @param url    请求数据的uri地址，如 “https://api.weibo.com/2/location/pois/search/by_geo.json”,不包含问号”？“
     * @param params 参数列表
     * @return
     */
    public static Result getFromWebByHttpClient(String url, Map<String, String> params) {
        Result result = new Result();
        result.status = AppSignal.OK;
        try {
            result.object = getFromWebByHttpClient(DataCenter.context, url, params);
        } catch (Exception e) {
            handleException(e, result);
        }
        return result;
    }

    public static Result PostFromWebByHttpClient(String url, Map<String, String> params) {
        Result result = new Result();
        result.status = AppSignal.OK;
        try {
            result.object = PostFromWebByHttpClient(DataCenter.context, url, params);
        } catch (Exception e) {
            handleException(e, result);
        }
        return result;
    }

    private static void handleException(Exception e, Result result) {
        e.printStackTrace();
        if (e.getMessage() == null ) {
            return;
        }
        Log.e(TAG, "|" + e.getMessage() + "|");
        if (e.getMessage().equals(DataCenter.context.getResources().getString(R.string.SC_NOT_FOUND))) {
            result.status = AppSignal.SC_NOT_FOUND;
        } else if (e.getMessage().equals(DataCenter.context.getResources().getString(R.string.TimeOut))) {
            result.status = AppSignal.RPC_TIMEOUT;
        } else if (e.getMessage().equals(DataCenter.context.getResources().getString(R.string.HTTP_ERROR))) {
            result.status = AppSignal.HTTP_ERROR;
        } else {
            result.status = AppSignal.OTHER_ERROR;
        }

    }


    //-------------------------------------http请求二次封装----------------------------------------------------------

    /**
     * HttpClient get方法
     *
     * @param url
     * @param params
     * @return
     */
    public static String getFromWebByHttpClient(Context context, String url,
                                                Map<String, String> params) {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        if (params.size() > 0) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                String key = entry.getKey().toString();
                String value = entry.getValue().toString();
                nameValuePairs.add(new BasicNameValuePair(key, value));
            }
        }

        return getFromWebByHttpClient(context, url, nameValuePairs.toArray(new NameValuePair[nameValuePairs.size()]));
    }


    /**
     * HttpClient post方法
     *
     * @param url
     * @param params
     * @return
     */
    public static String PostFromWebByHttpClient(Context context, String url,
                                                 Map<String, String> params) {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String key = entry.getKey().toString();
            String value = entry.getValue().toString();
            nameValuePairs.add(new BasicNameValuePair(key, value));
        }
        return PostFromWebByHttpClient(context, url, nameValuePairs.toArray(new NameValuePair[nameValuePairs.size()]));
    }

    //=======================================一以下三个方法是http原始请求==========================================================

    /**
     * HttpClient post方法
     *
     * @param url
     * @param nameValuePairs
     * @return
     */
    public static String PostFromWebByHttpClient(Context context, String url,
                                                 NameValuePair... nameValuePairs) {
        try {
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            if (nameValuePairs != null) {
                for (int i = 0; i < nameValuePairs.length; i++) {
                    params.add(nameValuePairs[i]);
                }
            }
            UrlEncodedFormEntity urlEncoded = new UrlEncodedFormEntity(params,
                    CHARSET_UTF8);

            HttpPost httpPost = new HttpPost(url);
            Log.d(TAG, "PostFromWebByHttpClient url = " + url + ";" + params);
            httpPost.setEntity(urlEncoded);
            HttpClient client = getHttpClient(context);
            HttpResponse response = client.execute(httpPost);
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                String str = "";
                switch (response.getStatusLine().getStatusCode()) {
                    case HttpStatus.SC_NOT_FOUND:
                        str = context.getResources().getString(R.string.SC_NOT_FOUND);
                        break;
                    case HttpStatus.SC_REQUEST_TIMEOUT:
                        str = context.getResources().getString(R.string.TimeOut);
                        break;
                    case HttpStatus.SC_GATEWAY_TIMEOUT:
                        str = context.getResources().getString(R.string.TimeOut);
                        break;
                    default:
                        str = context.getResources().getString(R.string.HTTP_ERROR);
                }
                throw new RuntimeException(str);
            }
            HttpEntity resEntity = response.getEntity();

            return (resEntity == null) ? null : EntityUtils.toString(resEntity,
                    CHARSET_UTF8);
        } catch (UnsupportedEncodingException e) {
            Log.w(TAG, e.getMessage());
            return null;
        } catch (ClientProtocolException e) {
            Log.w(TAG, e.getMessage());
            return null;
        }  catch (ConnectTimeoutException e) {
            throw new RuntimeException(context.getResources().getString(
                    R.string.TimeOut), e);
        } catch (IOException e) {
            throw new RuntimeException(context.getResources().getString(
                    R.string.IOException), e);
        }
    }

    public static String getFromWebByHttpClient(Context context, String url,
                                                NameValuePair... nameValuePairs) {
        try {
            // http地址
            // String httpUrl =
            // "http://192.168.1.110:8080/httpget.jsp?par=HttpClient_android_Get";
            StringBuilder sb = new StringBuilder();
            sb.append(url);
            if (nameValuePairs != null && nameValuePairs.length > 0) {
                sb.append("?");
                for (int i = 0; i < nameValuePairs.length; i++) {
                    if (i > 0) {
                        sb.append("&");
                    }
                    sb.append(String.format("%s=%s",
                            nameValuePairs[i].getName(),
                            nameValuePairs[i].getValue()));
                }
            }
            Log.d(TAG, "getFromWebByHttpClient url = " + sb.toString());

            // HttpGet连接对象
            HttpGet httpRequest = new HttpGet(sb.toString());
            // 取得HttpClient对象
            HttpClient httpclient = getHttpClient(context);
            // 请求HttpClient，取得HttpResponse
            HttpResponse httpResponse = httpclient.execute(httpRequest);
            // 请求成功
            if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                String str = "";
                switch (httpResponse.getStatusLine().getStatusCode()) {
                    case HttpStatus.SC_NOT_FOUND:
                        str = context.getResources().getString(R.string.SC_NOT_FOUND);
                        break;
                    case HttpStatus.SC_REQUEST_TIMEOUT:
                        str = context.getResources().getString(R.string.TimeOut);
                        break;
                    case HttpStatus.SC_GATEWAY_TIMEOUT:
                        str = context.getResources().getString(R.string.TimeOut);
                        break;
                    default:
                        str = context.getResources().getString(R.string.HTTP_ERROR);
                }
                throw new RuntimeException(str);
            }
            return EntityUtils.toString(httpResponse.getEntity());
        } catch (ParseException e) {
            throw new RuntimeException(context.getResources().getString(
                    R.string.ParseException), e);
        } catch (ConnectTimeoutException e) {
            throw new RuntimeException(context.getResources().getString(
                    R.string.TimeOut), e);
        }  catch (IOException e) {
            Log.e(TAG, "IOException ");
            e.printStackTrace();
            throw new RuntimeException(context.getResources().getString(
                    R.string.IOException), e);
        }
    }

    /**
     * 创建httpClient实例
     *
     * @return
     * @throws Exception
     */
    private static synchronized HttpClient getHttpClient(Context context) {
        if (null == customerHttpClient) {
            HttpParams params = new BasicHttpParams();
            // 设置一些基本参数
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params, CHARSET_UTF8);
            HttpProtocolParams.setUseExpectContinue(params, true);
            HttpProtocolParams
                    .setUserAgent(
                            params,
                            "Mozilla/5.0(Linux;U;Android 2.2.1;en-us;Nexus One Build.FRG83) "
                                    + "AppleWebKit/553.1(KHTML,like Gecko) Version/4.0 Mobile Safari/533.1"
                    );
            // 超时设置
            /* 从连接池中取连接的超时时间 */
            ConnManagerParams.setTimeout(params, 2000);//1000
			/* 连接超时 */
            int ConnectionTimeOut = 3000;//3000
            if (!HttpUtils.isWifiDataEnable(context)) {
                ConnectionTimeOut = 10000; //10000
            }
            HttpConnectionParams
                    .setConnectionTimeout(params, ConnectionTimeOut);
			/* 请求超时 */
            HttpConnectionParams.setSoTimeout(params, 4000); //4000
            // 设置我们的HttpClient支持HTTP和HTTPS两种模式
            SchemeRegistry schReg = new SchemeRegistry();
            schReg.register(new Scheme("http", PlainSocketFactory
                    .getSocketFactory(), 80));
            schReg.register(new Scheme("https", SSLSocketFactory
                    .getSocketFactory(), 443));

            // 使用线程安全的连接管理来创建HttpClient
            ClientConnectionManager conMgr = new ThreadSafeClientConnManager(
                    params, schReg);
            customerHttpClient = new DefaultHttpClient(conMgr, params);
        }
        return customerHttpClient;
    }
}
